home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / MosaicSRC / libwww2 / HTWSRC.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-03-13  |  9.1 KB  |  425 lines

  1. /*            Parse WAIS Source file            HTWSRC.c
  2. **            ======================
  3. **
  4. **    This module parses a stream with WAIS source file
  5. **    format information on it and creates a structured stream.
  6. **    That structured stream is then converted into whatever.
  7. **
  8. **    3 June 93    Bug fix: Won't crash if no description
  9. */
  10.  
  11. #include "HTWSRC.h"
  12.  
  13. #include <stdio.h>
  14. #include "HTML.h"
  15.  
  16. #include "HTUtils.h"
  17. #include "tcp.h"
  18. #include "HTParse.h"
  19.  
  20. #define BIG 10000        /* Arbitrary limit to value length */
  21. #define PARAM_MAX BIG
  22.  
  23. struct _HTStructured {
  24.     CONST HTStructuredClass *    isa;
  25.     /* ... */
  26. };
  27.  
  28. #define PUTC(c) (*me->target->isa->put_character)(me->target, c)
  29. #define PUTS(s) (*me->target->isa->put_string)(me->target, s)
  30. #define START(e) (*me->target->isa->start_element)(me->target, e, 0, 0)
  31. #define END(e) (*me->target->isa->end_element)(me->target, e)
  32.  
  33.  
  34. /*    Here are the parameters which can be specified in a  source file
  35. */
  36. PRIVATE CONST char* par_name[] = {
  37.     "version", 
  38.     "ip-address",
  39. #define PAR_IP_NAME 2
  40.     "ip-name", 
  41. #define PAR_TCP_PORT 3
  42.     "tcp-port", 
  43. #define PAR_DATABASE_NAME 4
  44.     "database-name",
  45. #define PAR_COST 5
  46.     "cost", 
  47. #define PAR_COST_UNIT 6
  48.     "cost-unit", 
  49. #define PAR_FREE 7
  50.     "free",    
  51. #define PAR_MAINTAINER 8
  52.     "maintainer",     
  53. #define PAR_DESCRIPTION 9
  54.     "description",
  55.     "keyword-list",     
  56.     "source",
  57. #define PAR_UNKNOWN 12
  58.     "unknown",
  59.     0,                /* Terminate list */
  60. #define PAR_COUNT 13
  61. } ;
  62.  
  63.  
  64. enum tokenstate { beginning, before_tag, colon, before_value,
  65.         value, bracketed_value, quoted_value, escape_in_quoted, done };
  66.  
  67.  
  68. /*        Stream Object
  69. **        ------------
  70. **
  71. **    The target is the structured stream down which the
  72. **    parsed results will go.
  73. **
  74. **    all the static stuff below should go in here to make it reentrant
  75. */
  76.  
  77. struct _HTStream {
  78.     CONST HTStreamClass *    isa;
  79.     HTStructured *        target;
  80.     char *            par_value[PAR_COUNT];
  81.     enum tokenstate     state;
  82.     char             param[BIG+1];
  83.     int            param_number;
  84.     int            param_count;
  85. };
  86.  
  87.  
  88.  
  89.  
  90. PUBLIC CONST char * hex = "0123456789ABCDEF";
  91.  
  92. /*    Decode one hex character
  93. */
  94.  
  95. PUBLIC char from_hex ARGS1(char, c)
  96. {
  97.     return           (c>='0')&&(c<='9') ? c-'0'
  98.             : (c>='A')&&(c<='F') ? c-'A'+10
  99.             : (c>='a')&&(c<='f') ? c-'a'+10
  100.             :               0;
  101. }
  102.  
  103.  
  104. /*            State machine
  105. **            -------------
  106. **
  107. ** On entry,
  108. **    me->state    is a valid state (see WSRC_init)
  109. **    c        is the next character
  110. ** On exit,
  111. **     returns    1    Done with file
  112. **        0    Continue. me->state is updated if necessary.
  113. **        -1    Syntax error error
  114. */
  115.  
  116.  
  117. /*        Treat One Character
  118. **        -------------------
  119. */
  120. PRIVATE void WSRCParser_put_character ARGS2(HTStream*, me, char, c)
  121. {
  122.     switch (me->state) {
  123.     case beginning:
  124.         if (c=='(') me->state = before_tag;
  125.     break;
  126.     
  127.     case before_tag:
  128.         if (c==')') {
  129.         me->state = done;
  130.         return;            /* Done with input file */
  131.     } else if (c==':') {
  132.         me->param_count = 0;
  133.         me->state = colon;
  134.     }                /* Ignore other text */
  135.     break;
  136.  
  137.     case colon:
  138.         if (WHITE(c)) {
  139.         me->param[me->param_count++] = 0;    /* Terminate */
  140.         for(me->param_number = 0; par_name[me->param_number]; me->param_number++) {
  141.         if (0==strcmp(par_name[me->param_number], me->param)) {
  142.             break;
  143.         }
  144.         }
  145.         if (!par_name[me->param_number]) {    /* Unknown field */
  146.             if (TRACE) fprintf(stderr,
  147.             "HTWSRC: Unknown field `%s' in source file\n",
  148.             me->param);
  149.         me->param_number = PAR_UNKNOWN;
  150.         me->state = before_value;    /* Could be better ignore */
  151.         return;
  152.         }
  153.         me->state = before_value;
  154.     } else {
  155.         if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  156.     }
  157.     break;
  158.     
  159.     case before_value:
  160.         if (c==')') {
  161.         me->state = done;
  162.         return;            /* Done with input file */
  163.     }
  164.     if (WHITE(c)) return;        /* Skip white space */
  165.     me->param_count = 0;
  166.     if (c=='"') {
  167.         me->state = quoted_value;
  168.         break;
  169.     }
  170.     me->state = (c=='"') ? quoted_value : 
  171.             (c=='(') ? bracketed_value : value;
  172.     me->param[me->param_count++] = c;    /* Don't miss first character */
  173.     break;
  174.  
  175.     case value:
  176.         if (WHITE(c)) {
  177.         me->param[me->param_count] = 0;
  178.         StrAllocCopy(me->par_value[me->param_number], me->param);
  179.         me->state = before_tag;
  180.     } else {
  181.         if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  182.     }
  183.     break;
  184.  
  185.     case bracketed_value:
  186.         if (c==')') {
  187.         me->param[me->param_count] = 0;
  188.         StrAllocCopy(me->par_value[me->param_number], me->param);
  189.         me->state = before_tag;
  190.         break;
  191.     }
  192.         if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  193.     break;
  194.     
  195.     case quoted_value:
  196.         if (c=='"') {
  197.         me->param[me->param_count] = 0;
  198.         StrAllocCopy(me->par_value[me->param_number], me->param);
  199.         me->state = before_tag;
  200.         break;
  201.     }
  202.     
  203.     if (c=='\\') {        /* Ignore escape but switch state */
  204.         me->state = escape_in_quoted;
  205.         break;
  206.     }
  207.     if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  208.     break;
  209.  
  210.     case escape_in_quoted:
  211.         if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  212.     me->state = quoted_value;
  213.     break;
  214.     
  215.     case done:                /* Ignore anything after EOF */
  216.     return;
  217.  
  218.     } /* switch me->state */
  219. }
  220.  
  221.  
  222. /*            Output equivalent HTML
  223. **            ----------------------
  224. **
  225. */
  226.  
  227. void give_parameter ARGS2(HTStream *, me, int, p)
  228. {
  229.     PUTS(par_name[p]);
  230.     if (me->par_value[p]) {
  231.     PUTS(": ");
  232.     PUTS(me->par_value[p]);
  233.     PUTS("; ");
  234.     } else {
  235.         PUTS(" NOT GIVEN in source file; ");
  236.     }
  237. }
  238.  
  239.  
  240. /*            Generate Outout
  241. **            ===============
  242. */
  243. PRIVATE void WSRC_gen_html ARGS2(HTStream *, me, BOOL, source_file)
  244.  
  245. {
  246.     if (me->par_value[PAR_DATABASE_NAME]) {
  247.     char * shortname = 0;
  248.     int l;
  249.     StrAllocCopy(shortname, me->par_value[PAR_DATABASE_NAME]);
  250.     l = strlen(shortname);
  251.     if ( l > 4 && !strcasecomp(shortname + l -4, ".src")) {
  252.         shortname[l-4] = 0;    /* Chop of .src -- boring! */
  253.     }
  254.     
  255.     START(HTML_TITLE);
  256.     PUTS(shortname);
  257.     PUTS(source_file ? " WAIS source file" : " index");
  258.     END(HTML_TITLE);
  259.     
  260.     START(HTML_H1);
  261.     PUTS(shortname);
  262.     PUTS(source_file ? " description" : " index");
  263.     END(HTML_H1);
  264.     }
  265.     
  266.     START(HTML_DL);        /* Definition list of details */
  267.     
  268.     if (source_file) {
  269.     START(HTML_DT);
  270.     PUTS("Access links");
  271.     START(HTML_DD);
  272.     if (me->par_value[PAR_IP_NAME] &&
  273.         me->par_value[PAR_DATABASE_NAME]) {
  274.     
  275.         char WSRC_address[256];
  276.         char * www_database;
  277.         www_database = HTEscape(me->par_value[PAR_DATABASE_NAME]);
  278.         sprintf(WSRC_address, "wais://%s:%s/%s",
  279.         me->par_value[PAR_IP_NAME],
  280.         me->par_value[PAR_TCP_PORT] ? me->par_value[PAR_TCP_PORT]
  281.             : "210",
  282.         www_database);
  283.     
  284.             PUTS ("<A HREF=\"");
  285.             PUTS (WSRC_address);
  286.             PUTS ("\">");
  287.         PUTS("Direct access");
  288.             PUTS("</A>");
  289.         
  290.         PUTS(" or ");
  291.         
  292.         sprintf(WSRC_address, "http://www.ncsa.uiuc.edu:8001/%s:%s/%s",
  293.         me->par_value[PAR_IP_NAME],
  294.         me->par_value[PAR_TCP_PORT] ? me->par_value[PAR_TCP_PORT]
  295.         : "210",
  296.         www_database);
  297.             PUTS ("<A HREF=\"");
  298.             PUTS (WSRC_address);
  299.             PUTS ("\">");
  300.         PUTS("through NCSA gateway");
  301.             PUTS("</A>");
  302.         
  303.         free(www_database);
  304.         
  305.     } else {
  306.         give_parameter(me, PAR_IP_NAME);
  307.         give_parameter(me, PAR_IP_NAME);
  308.     }
  309.     
  310.     } /* end if source_file */
  311.     
  312.     if (me->par_value[PAR_MAINTAINER]) {
  313.     START(HTML_DT);
  314.     PUTS("Maintainer");
  315.     START(HTML_DD);
  316.     PUTS(me->par_value[PAR_MAINTAINER]);
  317.     }
  318.     START(HTML_DT);
  319.     PUTS("Host");
  320.     START(HTML_DD);
  321.     PUTS(me->par_value[PAR_IP_NAME]);
  322.  
  323.     END(HTML_DL);
  324.  
  325.     if (me->par_value[PAR_DESCRIPTION]) {
  326.     START(HTML_PRE);        /* Preformatted description */
  327.     PUTS(me->par_value[PAR_DESCRIPTION]);
  328.     END(HTML_PRE);
  329.     }
  330.     
  331.     (*me->target->isa->end_document)(me->target);
  332.     (*me->target->isa->free)(me->target);
  333.     
  334.     return;
  335. } /* generate html */
  336.  
  337.  
  338. PRIVATE void WSRCParser_put_string ARGS2(HTStream *, context, CONST char*, str)
  339. {
  340.     CONST char *p;
  341.     for(p=str; *p; p++)
  342.         WSRCParser_put_character(context, *p);
  343. }
  344.  
  345.  
  346. PRIVATE void WSRCParser_write ARGS3(
  347.         HTStream *,     context,
  348.         CONST char*,     str,
  349.         int,         l)
  350. {
  351.     CONST char *p;
  352.     CONST char *e = str+l;
  353.     for(p=str; p<e; p++)
  354.         WSRCParser_put_character(context, *p);
  355. }
  356.  
  357.  
  358. PRIVATE void WSRCParser_free ARGS1(HTStream *, me)
  359. {
  360.     WSRC_gen_html(me, YES);
  361.     {
  362.     int p;
  363.     for(p=0; par_name[p]; p++) {    /* Clear out old values */
  364.         if (me->par_value[p]) {
  365.         free(me->par_value[p]);
  366.         }
  367.     }
  368.     }
  369.     free(me);
  370. }
  371.  
  372. PRIVATE void WSRCParser_end_document ARGS1(HTStream *, me)
  373. {
  374. /* Nothing */
  375. }
  376.  
  377. PRIVATE void WSRCParser_handle_interrupt ARGS1(HTStream *, me)
  378. {
  379. /* Nothing */
  380. }
  381.  
  382.  
  383. /*        Stream subclass        -- method routines
  384. **        ---------------
  385. */
  386.  
  387. HTStreamClass WSRCParserClass = {
  388.     "WSRCParser",
  389.     WSRCParser_free,
  390.     WSRCParser_end_document,
  391.     WSRCParser_put_character,
  392.      WSRCParser_put_string,
  393.     WSRCParser_write,
  394.         WSRCParser_handle_interrupt
  395.  
  396. };
  397.  
  398.  
  399. /*        Converter from WAIS Source to whatever
  400. **        --------------------------------------
  401. */
  402. PUBLIC HTStream* HTWSRCConvert ARGS5(
  403.     HTPresentation *,    pres,
  404.     HTParentAnchor *,    anchor,    
  405.     HTStream *,        sink,
  406.         HTFormat,                format_in,
  407.         int,                     compressed)
  408. {
  409.     HTStream * me = (HTStream*) malloc(sizeof(*me));
  410.  
  411.     me->isa = &WSRCParserClass;
  412.     me->target = HTML_new(NULL, pres->rep_out, sink);
  413.  
  414.     {
  415.     int p;
  416.     for(p=0; p < PAR_COUNT; p++) {    /* Clear out parameter values */
  417.         me->par_value[p] = 0;
  418.     }
  419.     }
  420.     me->state = beginning;
  421.  
  422.     return me;
  423. }
  424.  
  425.